﻿using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;

namespace NiuX.Dapper.Repositories;

/// <summary>
/// Dapper 仓储接口定义
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public partial interface IDapperRepository<TEntity> : IDapperRepository where TEntity : class, new()
{
    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>By default filters on the Id column</para>
    /// <para>-Id column name can be overridden by adding an attribute on your primary key property [Key]</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns a single entity by a single id from table T</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="id"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Returns a single entity by a single id from table T.</returns>
    TEntity Get(object id, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>whereConditions is an anonymous type to filter the results ex: new {Category = 1, SubCategory=2}</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns a list of entities that match where conditions</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="whereConditions"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Gets a list of entities with optional exact match where conditions</returns>
    IEnumerable<TEntity> GetList(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>conditions is an SQL where clause and/or order by clause ex: "where name='bob'" or "where age>=@Age"</para>
    /// <para>parameters is an anonymous type to pass in named parameter values: new { Age = 15 }</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns a list of entities that match where conditions</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="conditions"></param>
    /// <param name="parameters"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Gets a list of entities with optional SQL where conditions</returns>
    IEnumerable<TEntity> GetList(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Returns a list of all entities</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <returns>Gets a list of all entities</returns>
    IEnumerable<TEntity> GetList();

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>conditions is an SQL where clause ex: "where name='bob'" or "where age>=@Age" - not required </para>
    /// <para>orderby is a column or list of columns to order by ex: "lastname, age desc" - not required - default is by primary key</para>
    /// <para>parameters is an anonymous type to pass in named parameter values: new { Age = 15 }</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns a list of entities that match where conditions</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="pageNumber"></param>
    /// <param name="rowsPerPage"></param>
    /// <param name="conditions"></param>
    /// <param name="orderby"></param>
    /// <param name="parameters"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Gets a paged list of entities with optional exact match where conditions</returns>
    IEnumerable<TEntity> GetListPaged(int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Inserts a row into the database</para>
    /// <para>By default inserts into the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Insert filters out Id column and any columns with the [Key] attribute</para>
    /// <para>Properties marked with attribute [Editable(false)] and complex types are ignored</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns the ID (primary key) of the newly inserted record if it is identity using the int? type, otherwise null</para>
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="entityToInsert"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The ID (primary key) of the newly inserted record if it is identity using the int? type, otherwise null</returns>
    int? Insert(TEntity entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Updates a record or records in the database with only the properties of TEntity</para>
    /// <para>By default updates records in the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Updates records where the Id property and properties with the [Key] attribute match those in the database.</para>
    /// <para>Properties marked with attribute [Editable(false)] and complex types are ignored</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns number of rows affected</para>
    /// </summary>
    /// <param name="connection"></param>
    /// <param name="entityToUpdate"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The number of affected records</returns>
    int Update(TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Deletes a record or records in the database that match the object passed in</para>
    /// <para>-By default deletes records in the table matching the class name</para>
    /// <para>Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>Returns the number of records affected</para>
    /// </summary>
    /// <param name="entityToDelete"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The number of records affected</returns>
    int Delete(TEntity entityToDelete, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Deletes a record or records in the database by ID</para>
    /// <para>By default deletes records in the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Deletes records where the Id property and properties with the [Key] attribute match those in the database</para>
    /// <para>The number of records affected</para>
    /// <para>Supports transaction and command timeout</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="id"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The number of records affected</returns>
    int Delete(object id, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Deletes a list of records in the database</para>
    /// <para>By default deletes records in the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Deletes records where that match the where clause</para>
    /// <para>whereConditions is an anonymous type to filter the results ex: new {Category = 1, SubCategory=2}</para>
    /// <para>The number of records affected</para>
    /// <para>Supports transaction and command timeout</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="whereConditions"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The number of records affected</returns>
    int DeleteList(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>Deletes a list of records in the database</para>
    /// <para>By default deletes records in the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Deletes records where that match the where clause</para>
    /// <para>conditions is an SQL where clause ex: "where name='bob'" or "where age>=@Age"</para>
    /// <para>parameters is an anonymous type to pass in named parameter values: new { Age = 15 }</para>
    /// <para>Supports transaction and command timeout</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="conditions"></param>
    /// <param name="parameters"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>The number of records affected</returns>
    int DeleteList(string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Returns a number of records entity by a single id from table T</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>conditions is an SQL where clause ex: "where name='bob'" or "where age>=@Age" - not required </para>
    /// <para>parameters is an anonymous type to pass in named parameter values: new { Age = 15 }</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="conditions"></param>
    /// <param name="parameters"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Returns a count of records.</returns>
    int RecordCount(string conditions = "", object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// <para>By default queries the table matching the class name</para>
    /// <para>-Table name can be overridden by adding an attribute on your class [Table("YourTableName")]</para>
    /// <para>Returns a number of records entity by a single id from table T</para>
    /// <para>Supports transaction and command timeout</para>
    /// <para>whereConditions is an anonymous type to filter the results ex: new {Category = 1, SubCategory=2}</para>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="connection"></param>
    /// <param name="whereConditions"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <returns>Returns a count of records.</returns>
    int RecordCount(object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null);

    /// <summary>
    /// 连接上下文
    /// </summary>
    IDbConnection DbConnection { get; }

    /// <summary>
    /// 查询返回动态类型
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="param"></param>
    /// <param name="transaction"></param>
    /// <param name="buffered"></param>
    /// <param name="commandTimeout"></param>
    /// <param name="commandType"></param>
    /// <returns></returns>
    IEnumerable<object> Query(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);

    /// <summary>
    /// 查询返回特定类型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="sql"></param>
    /// <param name="param"></param>
    /// <param name="transaction"></param>
    /// <param name="buffered"></param>
    /// <param name="commandTimeout"></param>
    /// <param name="commandType"></param>
    /// <returns></returns>
    IEnumerable<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);

    List<object> QueryAsList(string sql, object param = null, IDbTransaction transaction = null,
        bool buffered = true,
        int? commandTimeout = null, CommandType? commandType = null);



    /// <summary>
    /// 查询返回特定类型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="sql"></param>
    /// <param name="param"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <param name="commandType"></param>
    /// <returns></returns>
    Task<IEnumerable<T>> QueryAsync<T>(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

    /// <summary>
    /// 执行命令
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="param"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <param name="commandType"></param>
    /// <returns></returns>
    int Execute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

    /// <summary>
    /// 执行命令
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="param"></param>
    /// <param name="transaction"></param>
    /// <param name="commandTimeout"></param>
    /// <param name="commandType"></param>
    /// <returns></returns>
    Task<int> ExecuteAsync(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

    void Dispose();
    ValueTask DisposeAsync();
}
